#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include "Sock.hpp"
#include "Log.hpp"
#include "Protocol.hpp"
static const uint16_t defaultport = 8080;

using namespace pr;

namespace ts
{
    using func_t = std::function<Response(const Request &)>;
    class Server;
    class ThreadData
    {
    public:
        ThreadData(int sock, std::string ip, uint16_t port, Server *current) : sock_(sock), ip_(ip), port_(port), current_(current)
        {
        }

        ~ThreadData() {}

    public:
        int sock_;
        std::string ip_;
        uint16_t port_;
        Server *current_;
    };

    class Server
    {
    public:
        Server(func_t func, uint16_t port = defaultport) : _func(func), _port(port)
        {
        }
        void InitServer()
        {
            // 1.创建套接字
            _sock.Socket();
            // 2.绑定
            _sock.Bind(_port);
            // 3.监听
            _sock.Listen();
            logMessage(Debug, "listen sock success,listensock: %d", _sock.Fd());
        }
        void Start()
        {
            while (true)
            {
                // 4.创建新的sock
                std::string clientip;
                uint16_t clientport;
                int sock = _sock.Accept(&clientip, &clientport);
                if (sock < 0)
                    continue;
                logMessage(Debug, "get a new client,info: [%s,%d]", clientip.c_str(), clientport);
                // 创建多线程处理服务:根据套接字处理相关服务
                pthread_t pt;
                ThreadData *td = new ThreadData(sock, clientip, clientport, this);
                pthread_create(&pt, nullptr, ThreadRoutine, td);
            }
        }
        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(args);
            // logMessage(Debug, "thread runing");
            td->current_->ServiceIO(td->sock_, td->ip_, td->port_);

            delete td;
            return nullptr;
        }
        void ServiceIO(int sock, const std::string &clientip, const uint16_t &clientport)
        {
            std::string Inffer;
            while (true)
            {
                // 1.获取单个完整的报文
                 // read/rev--获取数据：从sock中读取数据"7\r\n10 + 20\r\n"
                // string
                /*当出现这样的情景：
                客户端与服务器连接成功，客户端不断向服务器发送报文，服务器过一段时间对sock进行读取，此时sock中已经存在一大堆报文
                我们怎么保证从sock中获取的报文是单个完整的？*/
                std::string packet;
                int n = 0;
                n = ReadPacket(sock, Inffer, &packet);

                if (n == -1)
                {
                    break;
                }
                else if (n == 0)
                    continue;
                else
                {
                    // 2.去掉报头，获取序列化数据
                    packet = RemoveHeader(packet, n);
                    // 3.对数据进行反序列化
                    Request request;
                    if(!request.Deserialize(packet)) 
                    {
                        std::cout<<"request.Deserialize(packet) error"<<std::endl;
                        exit(-1);
                    }

                    // 4.进行业务逻辑处理:对请求进行业务处理，结果放在Response类中
                    Response response = _func(request);

                    // 5.对计算出来的结果进行序列化
                    std::string sendstr;
                    response.Serialize(&sendstr); // 序列化操作

                    // 6.添加报头
                    sendstr = AddHeader(sendstr);

                    // 7.将一个完整的报文结果发给客户端
                    send(sock, sendstr.c_str(), sendstr.size(), 0);
                }
            }
        }

        ~Server() 
        {
            _sock.Close();
        }

    private:
        uint16_t _port;
        Sock _sock;
        func_t _func;
    };
}